#include "MyChartViewVV.h"
#include <QApplication>
#include <QValueAxis>

MyChartViewVV::MyChartViewVV(QWidget* parent)
    : QChartView{ parent }
    , m_prevPoint{}
    , m_leftButtonPressed{}
    , m_ctrlPressed{}
    , m_alreadySaveRange{}
    , m_xRange{}
    , m_yRange{}
    , m_coordItem{}
{
    setDragMode(QGraphicsView::RubberBandDrag);
    setMouseTracking(false);
    setCursor(QCursor(Qt::PointingHandCursor));
}

MyChartViewVV::MyChartViewVV(QChart *chart, QWidget *parent)
    : MyChartViewVV{ parent } // C++11 Delegating constructors
{
    setChart(chart);
}

MyChartViewVV::~MyChartViewVV()
{
}

void MyChartViewVV::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        m_prevPoint = event->pos();
        m_leftButtonPressed = true;
    }
}

void MyChartViewVV::mouseMoveEvent(QMouseEvent *event)
{
    //鼠标的坐标
    if (!m_coordItem) {
        m_coordItem = new QGraphicsSimpleTextItem{ chart() };
        m_coordItem->setZValue(5);
        m_coordItem->setPos(100, 60);
        m_coordItem->show();
    }
    const QPoint curPos{ event->pos() };
    const QPointF curVal{ chart()->mapToValue(QPointF(curPos)) };
    m_coordItem->setText(QString("X = %1, Y = %2").arg(curVal.x()).arg(curVal.y()));

    if (m_leftButtonPressed) {
        const auto offset = curPos - m_prevPoint;
        m_prevPoint = curPos;
        if (!m_alreadySaveRange) {
            saveAxisRange();
            m_alreadySaveRange = true;
        }
        chart()->scroll(-offset.x(), offset.y());
    }
}

void MyChartViewVV::mouseReleaseEvent(QMouseEvent *event)
{
    m_leftButtonPressed = false;
    if (event->button() == Qt::RightButton) {
        if (m_alreadySaveRange) {
            chart()->axisX()->setRange(m_xRange[0], m_xRange[1]);
            chart()->axisY()->setRange(m_yRange[0], m_yRange[1]);
        }
    }
}

void MyChartViewVV::wheelEvent(QWheelEvent *event)
{
#if (QT_VERSION <= QT_VERSION_CHECK(6,0,0))
    const auto pos  = QPointF(event->pos());
    const auto isZoomIn = event->delta() > 0;
#else
    const auto pos  = event->position();
    const auto isZoomIn = event->angleDelta().y() > 0;
#endif
    const QPointF curVal = chart()->mapToValue(pos);

    if (!m_alreadySaveRange) {
        saveAxisRange();
        m_alreadySaveRange = true;
    }

    auto zoom = [](QValueAxis* axis, double centre, bool zoomIn) {
        constexpr auto scaling{ 1.5 };

        const double down = axis->min();
        const double up = axis->max();

        double downOffset{};
        double upOffset{};
        if (zoomIn) {
            downOffset = (centre - down) / scaling;
            upOffset = (up - centre) / scaling;
        }
        else {
            downOffset = (centre - down) * scaling;
            upOffset = (up - centre) * scaling;
        }

        axis->setRange(centre - downOffset, centre + upOffset);
    };

    if (m_ctrlPressed) {
        auto axis = qobject_cast<QValueAxis*>(chart()->axisY());
        zoom(axis, curVal.y(), isZoomIn);
    } else {
        auto axis = qobject_cast<QValueAxis*>(chart()->axisX());
        zoom(axis, curVal.x(), isZoomIn);
    }
}

void MyChartViewVV::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Control)
        m_ctrlPressed = true;
}

void MyChartViewVV::keyReleaseEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Control)
        m_ctrlPressed = false;
}

void MyChartViewVV::saveAxisRange()
{
    const auto axisX = qobject_cast<QValueAxis*>(chart()->axisX());
    m_xRange = { axisX->min(), axisX->max() };
    const auto axisY = qobject_cast<QValueAxis*>(chart()->axisY());
    m_yRange = { axisY->min(), axisY->max() };
}
